#include <gwbase/base/link_list.h>
#include <gwbase/base/test_harness.h>

using namespace dicom;

static int g_count = 0;

class Person: public LinkNode<Person> {
 public:
  Person(): id_(++g_count) { }
  virtual ~Person() {
    LOG_INFO << "destroy person: " << id_;
    --g_count;
  }
 private:
  int id_;
};

class LinkListTest { };

TEST(LinkListTest, Simple) {
  LinkList<Person> head;

  Person* p = new Person();
  Person* p2 = new Person();
  Person* p3 = new Person();
  head.append(p);
  p2->InsertBefore(p);
  p3->InsertAfter(p);

  EXPECT_TRUE (p->prev()->value() == p2);
  EXPECT_TRUE (p->next()->value() == p3);

  p->RemoveFromList();
  EXPECT_TRUE(!head.empty());

  p2->RemoveFromList();
  p3->RemoveFromList();
  EXPECT_TRUE(head.empty());

  delete p;
  delete p2;
  delete p3;

  EXPECT_Eq(g_count, 0);
}

TEST(LinkListTest, Iteration) {
  LinkList<Person> head;

  Person* p = new Person();
  Person* p2 = new Person();
  Person* p3 = new Person();
  head.append(p);
  p2->InsertBefore(p);
  p3->InsertAfter(p);

  for (LinkNode<Person>* it = head.begin(); it != head.end(); )
  {
    Person* p = it->value();
    it = it->next();
    p->RemoveFromList();
    delete p;
  }

  EXPECT_Eq(g_count, 0);
}

TEST(LinkListTest, ReverseIteration) {
  LinkList<Person> head;

  Person* p = new Person();
  Person* p2 = new Person();
  Person* p3 = new Person();
  head.append(p);
  p2->InsertBefore(p);
  p3->InsertAfter(p);

  for (LinkNode<Person>* it = head.rbegin(); it != head.rend(); )
  {
    Person* p = it->value();
    it = it->prev();
    p->RemoveFromList();
    delete p;
  }

  EXPECT_Eq(g_count, 0);
}

int main()
{
  RunAllTests();
}
